package com.zrj.auth.config;


import cn.binarywang.wx.miniapp.api.WxMaService;
import com.zrj.auth.core.extensions.mobile.SmsCodeAuthenticationProvider;
import com.zrj.auth.core.extensions.wechat.WechatAuthenticationProvider;
import com.zrj.auth.core.extensions.wechat.WechatAuthenticationToken;
import com.zrj.auth.core.userdetails.mobile.MemberUserDetailsServiceImpl;
import com.zrj.auth.core.userdetails.user.SysUserDetailsServiceImpl;
import com.zrj.auth.service.IUmsMemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


/**
 * @author zhaorujie
 */
@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final SysUserDetailsServiceImpl sysUserDetailsService;
    private final MemberUserDetailsServiceImpl memberUserDetailsService;
    private final IUmsMemberService umsMemberService;
    private final WxMaService wxMaService;

    /**
     * 配置安全拦截策略
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().antMatchers("/oauth/**", "login").permitAll()
                .antMatchers("/webjars/**", "/doc.html", "/swagger-resources/**", "/v2/api-docs").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf()
                .disable()
                .httpBasic();

//        http
//                .authorizeRequests()
//                .anyRequest()
//                .permitAll()
//                .and()
//                .csrf()
//                .disable()
//                .httpBasic();
    }

    /**
     * authenticationManager对象在oauth2认证服务中要是用，所有通过@bea注解提前放入IOC容器中
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth
                //账号密码授权提供者
                .authenticationProvider(daoAuthenticationProvider())
                //手机验证码授权提供者
                .authenticationProvider(smsCodeAuthenticationProvider())
                //微信小程序授权提供者
                .authenticationProvider(wechatAuthenticationProvider());
    }

    /**
     * 账号密码认证授权提供者
     * @return
     */
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(sysUserDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        return daoAuthenticationProvider;
    }

    /**
     * 手机验证码认证授权提供者
     * @return
     */
    @Bean
    public SmsCodeAuthenticationProvider smsCodeAuthenticationProvider() {
        SmsCodeAuthenticationProvider provider = new SmsCodeAuthenticationProvider();
        provider.setUserDetailsService(memberUserDetailsService);
        return provider;
    }

    /**
     * 微信小程序认证授权提供者
     * @return
     */
    @Bean
    public WechatAuthenticationProvider wechatAuthenticationProvider() {
        WechatAuthenticationProvider provider = new WechatAuthenticationProvider();
        provider.setUserDetailsService(memberUserDetailsService);
        provider.setUmsMemberService(umsMemberService);
        provider.setWxMaService(wxMaService);
        return provider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        DelegatingPasswordEncoder passwordEncoder = (DelegatingPasswordEncoder)PasswordEncoderFactories.createDelegatingPasswordEncoder();
        passwordEncoder.setDefaultPasswordEncoderForMatches(NoOpPasswordEncoder.getInstance());
        return passwordEncoder;
    }
}
